home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Examples / Scrolling Demo / Modified Scrolling - Open! / Scrolling Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-06  |  23.9 KB  |  877 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Scrolling Demo.c - Modified version
  3. //
  4. // By Vern Jensen. Created sometime in 1997
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWFPSReport.h>
  9. #include <SWIncludes.h>
  10. #include <SWGameUtils.h>
  11.  
  12. #include "SWApplication.h"
  13. #include "Scrolling Demo.h"
  14.  
  15. #define kMaxWindowWidth                640            // User can expand window to this size
  16. #define kMaxWindowHeight            480
  17.  
  18. #define kWorldRectInset                0            // Make the SpriteWorld smaller?
  19.  
  20. #define    kInterlacedMode                false        // Skips every other line
  21. #define kSyncToVBL                    false        // Sync SpriteWorld to VBL?
  22. #define kMaxFPS                        30            // Set to 0 for unrestricted speed
  23.     
  24. #define    kSpriteMoveDelta            20            // Try 5, 10, 20, or 40
  25. #define kDiamondSpace                8            // How far apart the diamonds are spaced
  26.                                                 // (try 1!)
  27.  
  28. #define kSpriteMoveDistance            80            // How far the sprite can move from
  29.                                                 // the center of the screen, in pixels.
  30.                                                 // Try making this value higher!
  31.  
  32.     // Number of ticks to wait before changing tile image; 0 = change every frame
  33. #define kDiamondFrameRate            8            // How often diamond tiles change frames
  34. #define kWallFrameRate                120            // How often wall changes frames
  35.  
  36. #define kBWPictResIDOffset            100
  37. #define kTileWidth                    40
  38. #define kTileHeight                    40
  39. #define kTileMapRows                100
  40. #define kTileMapCols                150
  41.  
  42. #define kStartRow                    5            // Starting position of sprite
  43. #define kStartCol                    5            // in tile col and row
  44.  
  45.  
  46. #define    kLeftArrowKey                0x7B
  47. #define    kRightArrowKey                0x7C
  48. #define    kDownArrowKey                0x7D
  49. #define    kUpArrowKey                    0x7E
  50.  
  51. #define    kLeftKeyPad                    0x56
  52. #define    kRightKeyPad                0x58
  53. #define    kDownKeyPad                    0x54
  54. #define    kUpKeyPad                    0x5B
  55.  
  56. #define kEscKey                        0x35
  57.  
  58.  
  59. #define kNoKey                        0
  60. #define kLeftKey                    1
  61. #define kUpKey                        2
  62. #define kRightKey                    3
  63. #define kDownKey                    4
  64.  
  65.  
  66. enum tileIDs
  67. {
  68.     kWallTile,
  69.     kLastWallTile,
  70.     kGrassTile,
  71.     kBlackTile,
  72.     kDiamondTile,
  73.     kDiamondTile2,
  74.     kLastDiamondTile,
  75.     
  76.     kTunnelTile1,
  77.     kTunnelTile2,
  78.     kTunnelTile3,
  79.     kTunnelTile4,
  80.     kTunnelTile5,
  81.     kTunnelTile6,
  82.     kWireTile1,
  83.     kWireTile2,
  84.     
  85.     kMaxNumTiles
  86. };
  87.  
  88.  
  89.  
  90. /***********/
  91. /* Globals */
  92. /***********/
  93.  
  94. SpriteWorldPtr        gSpriteWorldP;
  95. SpriteLayerPtr        gSpriteLayerP;
  96. SpriteLayerPtr        gMouseSpriteLayerP;
  97. TileMapStructPtr    gTileMapStructP;
  98. TileMapPtr            gTileMap;
  99. SpritePtr            gSimpleSpriteP, gDiamondMeterSpriteP, gMouseSpriteP;
  100. DrawProcPtr            gSpriteDrawProc;
  101. DrawProcPtr            gScreenDrawProc;
  102. DoubleDrawProcPtr    gDoubleRectDrawProc;
  103. WindowPtr            gWindowP;
  104. Rect                gScreenMidRect;
  105. Boolean                gDone = false;
  106.  
  107. short                gNumDiamondsInMap = 0;    // Number of diamonds in the TileMap
  108. short                gNumDiamonds = 0;        // Number of diamonds sprite has collected
  109.  
  110. struct moveKeys        // Keeps track of which keys are up and which are down
  111. {
  112.     Boolean    up;
  113.     Boolean    right;
  114.     Boolean    down;
  115.     Boolean    left;
  116. } gKeys;
  117.  
  118.  
  119. ///--------------------------------------------------------------------------------------
  120. // Main
  121. ///--------------------------------------------------------------------------------------
  122.  
  123. void    main( void )
  124. {
  125.     Initialize(kNumberOfMoreMastersCalls);
  126.     
  127.     if (SWHasSystem7())
  128.     {
  129.         AllowKeyUpEvents();    // Part of SWGameUtils.c
  130.         SetCursor(*GetCursor(watchCursor));
  131.         
  132.         CreateSpriteWorld();
  133.         CreateBallSprite();
  134.         CreateDiamondMeterSprite();
  135.         CreateMouseSprite();
  136.         
  137.         SetCursor(&qd.arrow);
  138.         HideCursor();
  139.         
  140.         SetUpAnimation();
  141.         RunAnimation();
  142.         ShutDown();
  143.         
  144.         RestoreEventMask();    // Call this after AllowKeyUpEvents
  145.     }
  146.     else
  147.     {
  148.         CantRunOnThisMachine();
  149.     }
  150. }
  151.  
  152.  
  153. ///--------------------------------------------------------------------------------------
  154. // CreateSpriteWorld
  155. ///--------------------------------------------------------------------------------------
  156.  
  157. void    CreateSpriteWorld( void )
  158. {
  159.     Rect        offscreenRect, worldRect, windRect;
  160.     OSErr        err;
  161.     short        row, col;
  162.     short        resIDOffset;
  163.     WindowPeek    windowPeek;
  164.     WStateData    *wStateData;
  165.     
  166.     gWindowP = GetNewCWindow(129, NULL, (WindowPtr)-1L);
  167.     
  168.     if (gWindowP != NULL)
  169.     {
  170.             // Center window in screen
  171.         windRect = gWindowP->portRect;
  172.         if (qd.screenBits.bounds.bottom < 440 || qd.screenBits.bounds.right < 600)
  173.         {
  174.                 // We're running in 512x384, so make the window smaller so it can be moved
  175.             windRect.bottom -= 80;
  176.             windRect.right -= 80;
  177.             SizeWindow(gWindowP, windRect.right - windRect.left, 
  178.                         windRect.bottom - windRect.top, false);
  179.         }
  180.         
  181.         CenterRect(&windRect, &qd.screenBits.bounds);
  182.         
  183.         AlignRect(&windRect);
  184.         MoveWindow(gWindowP, windRect.left, windRect.top, false);
  185.         
  186.         ShowWindow(gWindowP);
  187.         SetPort(gWindowP);
  188.         
  189.         if (kInterlacedMode)
  190.             PaintRect(&gWindowP->portRect);    // Blacken window for Interlaced mode
  191.     }
  192.     else
  193.         CantFindResource();
  194.     
  195.         // Change window's standard size to its current size. (Used when zooming window.)
  196.     windowPeek = (WindowPeek)gWindowP;
  197.     wStateData = (WStateData *) *(windowPeek->dataHandle);
  198.     wStateData->stdState = (**(windowPeek->contRgn)).rgnBBox;
  199.  
  200.     
  201.     err = SWEnterSpriteWorld();
  202.     FatalError(err);
  203.     
  204.     
  205.     worldRect = gWindowP->portRect;
  206.     
  207.         // Set size of offscreen area
  208.     offscreenRect = worldRect;
  209.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  210.     offscreenRect.right = SW_MAX(offscreenRect.right, kMaxWindowWidth);
  211.     offscreenRect.bottom = SW_MAX(offscreenRect.bottom, kMaxWindowHeight);
  212.  
  213.         // Make offscreen area evenly divisible by tile width & height
  214.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  215.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  216.     
  217.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  218.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  219.     
  220.         // Create the scrolling sprite world
  221.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  222.             &worldRect, &offscreenRect, 0);
  223.     FatalError(err);
  224.     
  225.     
  226.             // Create the sprite layers
  227.     err = SWCreateSpriteLayer(&gSpriteLayerP);
  228.     FatalError(err);
  229.     err = SWCreateSpriteLayer(&gMouseSpriteLayerP);
  230.     FatalError(err);
  231.     
  232.         // add the layers to the world
  233.     SWAddSpriteLayer(gSpriteWorldP, gSpriteLayerP);            // Bottom layer
  234.     SWAddSpriteLayer(gSpriteWorldP, gMouseSpriteLayerP);    // Top layer
  235.  
  236.  
  237.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  238.     FatalError(err);
  239.     
  240.     err = SWCreateTileMap(&gTileMapStructP, kTileMapRows, kTileMapCols);
  241.     FatalError(err);
  242.     
  243.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  244.     gTileMap = gTileMapStructP->tileMap;
  245.     
  246.     SWSetSpriteLayerUnderTileLayer(gSpriteLayerP, 0);
  247.     
  248.  
  249.         // Determine whether to load B&W or color graphics
  250.     if (gSpriteWorldP->pixelDepth <= 2)
  251.         resIDOffset = kBWPictResIDOffset;
  252.     else
  253.         resIDOffset = 0;
  254.  
  255.         // Load first set of tiles
  256.     err = SWLoadTilesFromPictResource(
  257.         gSpriteWorldP, 
  258.         kWallTile,                // startTileID 
  259.         kLastDiamondTile,        // endTileID
  260.         200 + resIDOffset,        // pictResID
  261.         0,                        // maskResID
  262.         kNoMask,                // maskType
  263.         false,                    // partial mask?
  264.         1,                        // horizBorderWidth
  265.         1);                        // vertBorderHeight
  266.     FatalError(err);
  267.     
  268.         // Load masked set of tiles
  269.     err = SWLoadTilesFromPictResource(
  270.         gSpriteWorldP, 
  271.         kTunnelTile1,            // startTileID 
  272.         kWireTile2,                // endTileID
  273.         201 + resIDOffset,        // pictResID
  274.         401,                    // maskResID
  275.         kFatMask,                // maskType
  276.         true,                    // partial mask?
  277.         1,                        // horizBorderWidth
  278.         1);                        // vertBorderHeight
  279.     FatalError(err);
  280.  
  281.     
  282.         // Set up tileMap
  283.     for (row = 0; row < kTileMapRows; row++)
  284.     {
  285.         for (col = 0; col < kTileMapCols; col++)
  286.         {
  287.             if (row == 0 || col == 0 || row == kTileMapRows-1 || col == kTileMapCols-1)
  288.                 gTileMap[row][col] = kWallTile;
  289.             else if (row > kTileMapRows / 2)
  290.                 gTileMap[row][col] = kWireTile1;
  291.             else if ((row/kDiamondSpace)*kDiamondSpace == row && 
  292.                      (col/kDiamondSpace)*kDiamondSpace == col)
  293.             {
  294.                 gTileMap[row][col] = kDiamondTile;
  295.                 gNumDiamondsInMap++;
  296.             }
  297.             else
  298.                 gTileMap[row][col] = kGrassTile;
  299.         }
  300.     }
  301.     
  302.  
  303.         // Add tunnel to tileMap
  304.     row = kTileMapRows / 2;
  305.  
  306.     for (col = 1; col < kTileMapCols-1; col += 2)
  307.     {
  308.         gTileMap[row][col] = kTunnelTile1;
  309.         gTileMap[row][col+1] = kTunnelTile2;
  310.         gTileMap[row+1][col] = kTunnelTile4;
  311.         gTileMap[row+1][col+1] = kTunnelTile5;
  312.     }
  313.  
  314.     gSpriteDrawProc = SWStdSpriteDrawProc;
  315.     gScreenDrawProc = SWStdWorldDrawProc;
  316.     gDoubleRectDrawProc = NULL;
  317.     
  318.         // Determine what DrawProcs to use
  319.     if (gSpriteWorldP->pixelDepth >= 8)        // 8-bit, 16-bit, or 32-bit, for 68k and PPC
  320.     {
  321.         gSpriteDrawProc = BlitPixieMaskDrawProc;
  322.         gScreenDrawProc = BlitPixieRectDrawProc;
  323.         gDoubleRectDrawProc = BlitPixieDoubleRectDrawProc;
  324.         SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixiePartialMaskDrawProc);
  325.     }
  326.     else    // The AllBit blitters are available only when compiling for 68k.
  327.     {
  328. #if SW_68k
  329.         gSpriteDrawProc = BlitPixieAllBitMaskDrawProc;
  330.         gScreenDrawProc = BlitPixieAllBitRectDrawProc;
  331.         SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
  332. #endif
  333.     }
  334. }
  335.     
  336.  
  337. ///--------------------------------------------------------------------------------------
  338. // CreateBallSprite
  339. ///--------------------------------------------------------------------------------------
  340.  
  341. void    CreateBallSprite( void )
  342. {
  343.     OSErr                err;
  344.     
  345.         // Create the ball sprite
  346.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gSimpleSpriteP, NULL, 
  347.             128, 1, kFatMask);    
  348.     FatalError(err);
  349.     
  350.         // Set up the ball sprite
  351.     SWAddSprite(gSpriteLayerP, gSimpleSpriteP);
  352.     SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
  353.     SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  354.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  355.     SWSetSpriteDrawProc(gSimpleSpriteP, gSpriteDrawProc);
  356. }
  357.  
  358.  
  359. ///--------------------------------------------------------------------------------------
  360. // CreateDiamondMeterSprite
  361. ///--------------------------------------------------------------------------------------
  362.  
  363. void    CreateDiamondMeterSprite( void )
  364. {
  365.     short                spriteResID;
  366.     OSErr                err;
  367.     
  368.         // Calculate resource ID for diamond meter sprite
  369.     if (gSpriteWorldP->pixelDepth <= 2)
  370.         spriteResID = 302;
  371.     else
  372.         spriteResID = 202;
  373.     
  374.         // Create the diamond meter sprite
  375.     err = SWCreateSpriteFromPictResource(gSpriteWorldP,
  376.                 &gDiamondMeterSpriteP, 
  377.                 NULL,            // pointer to memory for sprite
  378.                 spriteResID,     // picture resource id
  379.                 402,            // mask resource id
  380.                 1,                 // max frames
  381.                 kPixelMask);        // mask type
  382.     FatalError(err);
  383.     
  384.     SWAddSprite(gSpriteLayerP, gDiamondMeterSpriteP);
  385.     SWSetSpriteDrawProc(gDiamondMeterSpriteP, gSpriteDrawProc);
  386. }
  387.  
  388.  
  389. ///--------------------------------------------------------------------------------------
  390. // CreateMouseSprite
  391. ///--------------------------------------------------------------------------------------
  392.  
  393. void    CreateMouseSprite( void )
  394. {
  395.     OSErr                err;
  396.     
  397.         // Create the mouse sprite
  398.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gMouseSpriteP, NULL, 
  399.             130, 1, kPixelMask);    
  400.     FatalError(err);
  401.  
  402.     SWAddSprite(gMouseSpriteLayerP, gMouseSpriteP);
  403.     SWSetSpriteDrawProc(gMouseSpriteP, gSpriteDrawProc);
  404. }
  405.  
  406. #pragma mark -
  407. ///--------------------------------------------------------------------------------------
  408. // SetUpAnimation
  409. ///--------------------------------------------------------------------------------------
  410.  
  411. void    SetUpAnimation( void )
  412. {
  413.     Rect        moveBoundsRect, worldRect;
  414.     
  415.     SWLockSpriteWorld(gSpriteWorldP);
  416.     
  417.         // Set up data used by the SmoothScrollingWorldMoveProc
  418.     gScreenMidRect = gSimpleSpriteP->curFrameP->frameRect;
  419.     worldRect = gSpriteWorldP->windRect;
  420.     OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  421.     CenterRect( &gScreenMidRect, &worldRect );
  422.     
  423.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  424.     SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
  425.     
  426.         // movement boundary = size of tileMap
  427.     SetRect(&moveBoundsRect, 0,0, kTileMapCols * kTileWidth, kTileMapRows * kTileHeight);
  428.     
  429.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  430.     SWSetScrollingWorldMoveProc(gSpriteWorldP, SmoothScrollingWorldMoveProc, gSimpleSpriteP);
  431.     
  432.     SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
  433.     
  434.         // Move visScrollRect to starting sprite position
  435.     SWMoveVisScrollRect(gSpriteWorldP, 
  436.         gSpriteWorldP->followSpriteP->destFrameRect.left - gSpriteWorldP->backRect.right/2,
  437.         gSpriteWorldP->followSpriteP->destFrameRect.top - gSpriteWorldP->backRect.bottom/2);
  438.     
  439.         // Set starting position of diamond meter sprite
  440.     DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  441.     
  442.     SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  443.     SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  444.     SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);
  445.     
  446.         // Make sure CopyBits, if used, doesn't try to colorize things
  447.     SWSetPortToWindow(gSpriteWorldP);
  448.     ForeColor(blackColor);
  449.     BackColor(whiteColor);
  450.     
  451.     if (kInterlacedMode)
  452.     {
  453.         SWSetFrameInterlacingMode(gSpriteWorldP->workFrameP, true, kSkipOddLines);
  454.         SWSetFrameInterlacingMode(gSpriteWorldP->windowFrameP, true, kSkipOddLines);
  455.         
  456.         SWSetPortToWorkArea(gSpriteWorldP);
  457.         PaintRect(&gSpriteWorldP->backRect);
  458.     }
  459.     
  460.     SWDrawTilesInBackground(gSpriteWorldP);
  461.     SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
  462.     InitCursor();
  463. }
  464.  
  465.  
  466. ///--------------------------------------------------------------------------------------
  467. //  RunAnimation
  468. ///--------------------------------------------------------------------------------------
  469.  
  470. void    RunAnimation( void )
  471. {
  472.     EventRecord            event;
  473.     unsigned long        frames;
  474.     
  475.     frames = 0;
  476.     StartTimer();
  477.  
  478.     SetPort(gWindowP);
  479.     
  480.     while (!gDone)
  481.     {
  482.         if ( WaitNextEvent(everyEvent, &event, 0L, NULL) )
  483.             DispatchEvent(&event);
  484.  
  485.             // Make sure window wasn't "rolled up" with WindowShade
  486.         if ( !EmptyRgn( gWindowP->visRgn ) )
  487.         {
  488.             SWProcessScrollingSpriteWorld(gSpriteWorldP);
  489.     
  490.                 // Move diamond meter & mouse sprites to new visScrollRect location
  491.             DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  492.             MouseSpriteMoveProc(gMouseSpriteP);
  493.                 
  494.             SWAnimateScrollingSpriteWorld(gSpriteWorldP);
  495.             
  496.             if (gSpriteWorldP->frameHasOccurred)
  497.                 frames++;
  498.         }
  499.     }
  500.     
  501.     ShowResults(frames);
  502. }
  503.  
  504. ///--------------------------------------------------------------------------------------
  505. //  DispatchEvent
  506. ///--------------------------------------------------------------------------------------
  507.  
  508. void DispatchEvent(EventRecord* event)
  509. {
  510.     short            theKey, theChar;
  511.     Boolean            isDown;
  512.     
  513.     switch(event->what)
  514.     {
  515.         case mouseDown:
  516.             HandleMouseDown( event );
  517.             break;
  518.         case mouseUp:
  519.             break;
  520.         case keyUp:
  521.         case keyDown:
  522.         case autoKey:
  523.             theKey = (event->message & keyCodeMask) >> 8;
  524.             theChar = event->message & charCodeMask;
  525.             isDown = (event->what != keyUp);
  526.             
  527.             if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
  528.                 gKeys.left = isDown;
  529.             else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
  530.                 gKeys.right = isDown;
  531.             else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
  532.                 gKeys.down = isDown;
  533.             else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
  534.                 gKeys.up = isDown;
  535.             else if ( (theKey == kEscKey) || (theChar == 'Q') || (theChar == 'q') )
  536.                 gDone = true;
  537.             break;
  538.             break;
  539.         case updateEvt:
  540.             BeginUpdate(gWindowP);
  541.             SWUpdateScrollingSpriteWorld( gSpriteWorldP , true );
  542.             EndUpdate(gWindowP);
  543.             break;
  544.         case diskEvt:
  545.             break;
  546.         case activateEvt:
  547.             break;
  548.         case networkEvt:
  549.             break;
  550.         case driverEvt:
  551.             break;
  552.         case app1Evt:
  553.             break;
  554.         case app2Evt:
  555.             break;
  556.         case app3Evt:
  557.             break;
  558.         case osEvt:
  559.             if ( ( event->message & suspendResumeMessage ) == resumeFlag )
  560.             {
  561.                 SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  562.                 SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);
  563.             }
  564.             else
  565.             {
  566.                 SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, SWStdWorldDrawProc);
  567.                 SWSetDoubleRectDrawProc(gSpriteWorldP, NULL);
  568.             }
  569.             break;
  570.         case kHighLevelEvent:
  571.             break;
  572.         default:
  573.         break;
  574.     }
  575. }
  576.  
  577.  
  578. ///--------------------------------------------------------------------------------------
  579. //  HandleMouseDown
  580. ///--------------------------------------------------------------------------------------
  581.  
  582. void    HandleMouseDown( EventRecord *eventPtr )
  583. {
  584.     WindowPtr        theWindow;
  585.     Rect            windRect;
  586.     short            thePart;
  587.     Point            thePoint;
  588.     long            windowSize;
  589.     Rect            worldRect;
  590.     
  591.     
  592.     thePoint = eventPtr->where;
  593.     thePart = FindWindow( thePoint, &theWindow );
  594.  
  595.     switch ( thePart )
  596.     {
  597.         case inSysWindow : 
  598.             SystemClick( eventPtr, theWindow );
  599.             break;
  600.         case inDrag:
  601.             DragWindow( theWindow, thePoint, &((**(GetGrayRgn())).rgnBBox) );
  602.             windRect = (*((WindowPeek)gWindowP)->contRgn)->rgnBBox;
  603.             
  604.             AlignRect(&windRect);
  605.             MoveWindow(gWindowP, windRect.left, windRect.top, false);
  606.             
  607.             SWWindowMoved( gSpriteWorldP );
  608.             break;
  609.         case inZoomOut:
  610.         case inZoomIn:
  611.             if ( TrackBox(theWindow, thePoint, thePart) )
  612.             {
  613.                 ZoomWindow(theWindow, thePart, true);
  614.                 SWChangeWorldRect( gSpriteWorldP, &theWindow->portRect, false);
  615.                 SWDrawTilesInBackground( gSpriteWorldP );
  616.                 SWUpdateScrollingSpriteWorld( gSpriteWorldP , false );
  617.             
  618.                     // Reset data used by SmoothScrollingWorldMoveProc
  619.                 worldRect = gSpriteWorldP->windRect;
  620.                 OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  621.                 CenterRect( &gScreenMidRect, &worldRect );
  622.             }
  623.             break;
  624.         case inMenuBar:
  625.             break;
  626.         case inGoAway:
  627.             if ( TrackGoAway(theWindow, thePoint) )
  628.                 gDone = true;
  629.             break;
  630.         case inGrow:
  631.             SetRect(&windRect, 80, 80, 
  632.                 gSpriteWorldP->originalBackRect.right - gSpriteWorldP->originalBackRect.left+1, 
  633.                 gSpriteWorldP->originalBackRect.bottom - gSpriteWorldP->originalBackRect.top+1); 
  634.             windowSize = GrowWindow( theWindow, eventPtr->where, &windRect );
  635.             SizeWindow( theWindow, LoWord(windowSize), HiWord(windowSize), true);
  636.             SWChangeWorldRect( gSpriteWorldP, &theWindow->portRect, false);
  637.             SWDrawTilesInBackground( gSpriteWorldP );
  638.             SWUpdateScrollingSpriteWorld( gSpriteWorldP , false );
  639.             
  640.                 // Reset data used by SmoothScrollingWorldMoveProc
  641.             worldRect = gSpriteWorldP->windRect;
  642.             OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  643.             CenterRect( &gScreenMidRect, &worldRect );
  644.             break;
  645.         case inContent:
  646.             break;
  647.     }
  648. }
  649.  
  650.  
  651. ///--------------------------------------------------------------------------------------
  652. //  ShutDown (clean up and dispose of the SpriteWorld)
  653. ///--------------------------------------------------------------------------------------
  654.  
  655. void    ShutDown( void )
  656. {
  657.     SWDisposeSpriteWorld(&gSpriteWorldP);
  658.     SWExitSpriteWorld();
  659.     
  660.     FlushEvents(everyEvent, 0);
  661.     ShowCursor();
  662. }
  663.  
  664. #pragma mark -
  665. ///--------------------------------------------------------------------------------------
  666. //  TileChangeProc
  667. ///--------------------------------------------------------------------------------------
  668.  
  669. SW_FUNC void TileChangeProc(
  670.     SpriteWorldPtr spriteWorldP)
  671. {
  672.     short            curImage;
  673.     static short    wallDelay = 0, diamondDelay = 0;
  674.     static short    oldTicks = 0;
  675.     short            ticksPassed, ticks;
  676.     
  677.         // Initialize oldTicks the first time this function is called
  678.     if (oldTicks == 0)
  679.         oldTicks = TickCount();
  680.     
  681.     ticks = TickCount();
  682.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  683.     oldTicks = ticks;
  684.     
  685.         // kWallTile
  686.     wallDelay += ticksPassed;
  687.     if (wallDelay >= kWallFrameRate)
  688.     {
  689.         curImage = spriteWorldP->curTileImage[kWallTile];
  690.         if (curImage < kLastWallTile)
  691.             curImage++;
  692.         else
  693.             curImage = kWallTile;
  694.         
  695.         SWChangeTileImage(spriteWorldP, kWallTile, curImage);
  696.         wallDelay = 0;
  697.     }
  698.     
  699.     
  700.         // kDiamondTile
  701.     diamondDelay += ticksPassed;
  702.     if (diamondDelay >= kDiamondFrameRate)
  703.     {
  704.         curImage = spriteWorldP->curTileImage[kDiamondTile];
  705.         if (curImage < kLastDiamondTile)
  706.             curImage++;
  707.         else
  708.             curImage = kDiamondTile;
  709.         
  710.         SWChangeTileImage(spriteWorldP, kDiamondTile, curImage);
  711.         diamondDelay = 0;
  712.     }
  713. }
  714.  
  715.  
  716. ///--------------------------------------------------------------------------------------
  717. //  KeySpriteMoveProc
  718. ///--------------------------------------------------------------------------------------
  719.  
  720. SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
  721. {
  722.     short    row, col;
  723.     short    rowDelta, colDelta;
  724.     short    tile;
  725.     
  726.     
  727.     row = SWGetSpriteVertLoc(srcSpriteP) / kTileHeight;
  728.     col = SWGetSpriteHorizLoc(srcSpriteP) / kTileWidth;
  729.  
  730.     if (row * kTileHeight == SWGetSpriteVertLoc(srcSpriteP) &&
  731.         col * kTileWidth == SWGetSpriteHorizLoc(srcSpriteP))
  732.     {
  733.         tile = gTileMap[row][col];
  734.         
  735.             // Leave black trail behind sprite
  736.         if (tile == kGrassTile || tile == kDiamondTile)
  737.             SWDrawTile(gSpriteWorldP, 0, row, col, kBlackTile);
  738.         else if (tile == kTunnelTile2 || tile == kTunnelTile5 || tile == kWireTile1)
  739.             SWDrawTile(gSpriteWorldP, 0, row, col, tile+1);
  740.             
  741.         if (tile == kDiamondTile)
  742.         {
  743.             gNumDiamonds++;            // Increase number of diamonds sprite has collected
  744.             UpdateDiamondMeter();    // Update meter
  745.         }
  746.         
  747.  
  748.         rowDelta = 0;
  749.         colDelta = 0;
  750.         
  751.         if (gKeys.left)
  752.             colDelta = -1;
  753.         else if (gKeys.right)
  754.             colDelta = 1;
  755.         else if (gKeys.up)
  756.             rowDelta = -1;
  757.         else if (gKeys.down)
  758.             rowDelta = 1;
  759.         
  760.                 
  761.         
  762.         tile = gTileMap[row + rowDelta][col + colDelta];
  763.         
  764.         if (tile != kWallTile && tile != kTunnelTile1 && tile != kTunnelTile4)
  765.         {
  766.             srcSpriteP->vertMoveDelta = rowDelta * kSpriteMoveDelta;
  767.             srcSpriteP->horizMoveDelta = colDelta * kSpriteMoveDelta;
  768.         }
  769.         else
  770.         {
  771.             srcSpriteP->vertMoveDelta = 0;
  772.             srcSpriteP->horizMoveDelta = 0;
  773.         }
  774.     }
  775.     
  776.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  777. }
  778.  
  779.  
  780. ///--------------------------------------------------------------------------------------
  781. //  MouseSpriteMoveProc
  782. ///--------------------------------------------------------------------------------------
  783.  
  784. SW_FUNC void MouseSpriteMoveProc(SpritePtr srcSpriteP)
  785. {
  786.     Point                mousePoint;
  787.     
  788.         // Get mouse coordinates local to the window
  789.     SetPort(gWindowP);
  790.     GetMouse(&mousePoint);
  791.     
  792.         // Subtract any offset from worldRect to window if a worldRect is used
  793.     mousePoint.h -= gSpriteWorldP->windRect.left;
  794.     mousePoint.v -= gSpriteWorldP->windRect.top;
  795.     
  796.     SWMoveSprite(srcSpriteP, 
  797.         mousePoint.h - 1 + gSpriteWorldP->visScrollRect.left, 
  798.         mousePoint.v - 1 + gSpriteWorldP->visScrollRect.top);
  799. }
  800.  
  801.  
  802. ///--------------------------------------------------------------------------------------
  803. //  DiamondMeterSpriteMoveProc - not installed as a MoveProc, but called directly
  804. ///--------------------------------------------------------------------------------------
  805.  
  806. SW_FUNC void DiamondMeterSpriteMoveProc(SpritePtr srcSpriteP)
  807. {
  808.         // Move sprite to top-left corner of current visScrollRect location
  809.     SWMoveSprite(srcSpriteP, 
  810.         gSpriteWorldP->visScrollRect.left + 10, 
  811.         gSpriteWorldP->visScrollRect.top + 10);
  812. }
  813.  
  814.  
  815. ///--------------------------------------------------------------------------------------
  816. //  UpdateDiamondMeter - change the meter Sprite's image and mask
  817. ///--------------------------------------------------------------------------------------
  818.  
  819. SW_FUNC void UpdateDiamondMeter( void )
  820. {
  821.     double    percent;
  822.     Rect    meterRect;
  823.     
  824.     percent = (double)gNumDiamonds / gNumDiamondsInMap;
  825.     
  826.     SetRect(&meterRect, 17, 2, (108 * percent) + 17, 14);
  827.     
  828.     
  829.         // Set port to our sprite's framePort GWorld
  830.     SetGWorld(gDiamondMeterSpriteP->curFrameP->framePort, nil);
  831.     
  832.     ForeColor(magentaColor);
  833.     PaintRect(&meterRect);
  834.     
  835.     
  836.         // Set port to our sprite's pixel mask GWorld
  837.     SetGWorld(gDiamondMeterSpriteP->curFrameP->maskPort, nil);
  838.     
  839.         // Mask image is inverted when in 8-bit or less
  840.     if (gSpriteWorldP->pixelDepth <= 8)
  841.         ForeColor(whiteColor);
  842.     else
  843.         ForeColor(blackColor);
  844.     
  845.     PaintRect(&meterRect);
  846.     
  847.     
  848.         // Set sprite to be redrawn, since we've changed its image
  849.     gDiamondMeterSpriteP->needsToBeDrawn = true;
  850. }
  851.  
  852.  
  853. ///--------------------------------------------------------------------------------------
  854. //  SmoothScrollingWorldMoveProc - our scrolling WorldMoveProc
  855. ///--------------------------------------------------------------------------------------
  856.  
  857. SW_FUNC void SmoothScrollingWorldMoveProc(
  858.     SpriteWorldPtr spriteWorldP,
  859.     SpritePtr followSpriteP)
  860. {    
  861.     short    screenMidRectTop, screenMidRectLeft;
  862.     
  863.     screenMidRectTop = gScreenMidRect.top + spriteWorldP->visScrollRect.top;
  864.     screenMidRectLeft = gScreenMidRect.left + spriteWorldP->visScrollRect.left;
  865.     
  866.     
  867.     spriteWorldP->horizScrollDelta = (kSpriteMoveDelta * 
  868.         (SWGetSpriteHorizLoc(followSpriteP) - screenMidRectLeft) ) / kSpriteMoveDistance;
  869.     
  870.     spriteWorldP->vertScrollDelta = (kSpriteMoveDelta * 
  871.         (SWGetSpriteVertLoc(followSpriteP) - screenMidRectTop) ) / kSpriteMoveDistance;
  872.     
  873.     if (kInterlacedMode)
  874.         spriteWorldP->vertScrollDelta = spriteWorldP->vertScrollDelta>>1<<1;
  875. }
  876.  
  877.